#Warcraft 3 MDX parser

import os, sys
from Sanae3D.lib.StructReader import StructReader
from Sanae3D.lib.ModelObject import Model3D

class WarcraftIII_MDX(Model3D):
    
    def __init__(self, obj3D=None, outFile=None, inFile=None):
        
        super(WarcraftIII_MDX,self).__init__("XAC")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
	self.texList = []
	
    def make_material(self):
	
	pass
        
    def parse_ATCH(self):
        
        self.inFile.read_long()
        path = self.inFile.read_string(100)
        self.inFile.read_long()
        attachID = self.inFile.read_long()
	
    def parse_TEXS(self, chunkSize):
	
	texSize = 264
	numTex = chunkSize / texSize
	for i in range(numTex):
	    replaceID = self.inFile.read_long()
	    texName = self.inFile.read_string(0x100, "\x00")
	    unk, wrap = self.inFile.read_long(2)
	    self.texList.append(texName)
	    
	self.make_materials()
    
    def parse_MODL(self):
        
        name = self.inFile.read_string(0x150, "\x00")
        print name
        self.inFile.read_long()
        boundRadius = self.inFile.read_float()
        bbMin = self.inFile.read_float(3)
        bbMax = self.inFile.read_float(3)
        blendTime = self.inFile.read_long()        
        return name
    
    def parse_UVAS(self, meshName):
        
        numTex = self.inFile.read_long()
        for i in range(numTex):
            self.parse_UVBS(meshName)
    
    def parse_UVBS(self, meshName):
        
        self.inFile.read_string(4)
        numTex = self.inFile.read_long()
        for i in range(numTex):
            tu, tv = self.inFile.read_float(2)
	    
	    self.add_vert_uv(meshName, i, [tu, tv])
        
    def parse_MATS(self, meshName):
        '''Matrices'''
        
        count = self.inFile.read_long()
        for i in range(count):
            self.inFile.read_long()
            
        matID, selectGroup, selectable = self.inFile.read_long(3)
        boundRadius = self.inFile.read_float()
        bbMin = self.inFile.read_float(3)
        bbMax = self.inFile.read_float(3)
        numAnim = self.inFile.read_long()
        
        for i in range(numAnim):
            boundRadius = self.inFile.read_float()
            bbMin = self.inFile.read_float(3)
            bbMax = self.inFile.read_float(3)    
	    
	numFaces = self.face_count(meshName)
	for i in range(numFaces):
	    self.add_face_material(meshName, i, matID)
        
    def parse_MTGC(self):
        
        count = self.inFile.read_long()
        for i in range(count):
            self.inFile.read_long()
        
    def parse_GNDX(self):
        '''Vertex Groups'''
        
        count = self.inFile.read_long()
        for i in range(count):
            self.inFile.read_byte()
        
    def parse_PVTX(self, meshName):
        
        numFaces = self.inFile.read_long() / 3
        for i in range(numFaces):
            v1, v2, v3 = self.inFile.read_short(3)
	    
	    self.create_face(meshName, i)
	    self.add_face_verts(meshName, i, [v1, v2, v3])
        
    def parse_PCNT(self):
        
        count = self.inFile.read_long()
        for i in range(count):
            self.inFile.read_long()
        
    def parse_PTYP(self):
        
        count = self.inFile.read_long()
        for i in range(count):
            self.inFile.read_long()
        
    def parse_NRMS(self, meshName):
        
        numNorms = self.inFile.read_long()
        for i in range(numNorms):
            nx, ny, nz = self.inFile.read_float(3)
	    self.add_vert_normals(meshName, i, [nx, ny, nz])
        
    def parse_VRTX(self, meshName):
        
        numVerts = self.inFile.read_long()
        for i in range(numVerts):
            vx, vz, vy = self.inFile.read_float(3)
            self.create_vertex(meshName, i)
	    self.add_coords(meshName, i, [vx, vy, vz])
        
    def parse_GEOS(self, size, modelName):
        
        sectEnd = self.inFile.tell() + size
        meshNum = 0
        
        while self.inFile.tell() != sectEnd:
            chunkSize = self.inFile.read_long()
            chunkEnd = self.inFile.tell() + chunkSize - 4
	    meshName = "%s[%d]" %(modelName, meshNum)
	    self.create_object(meshName)
	    
            while self.inFile.tell() != chunkEnd:
                chunk = self.inFile.read_string(4)
		
                if chunk == "VRTX":
		    self.parse_VRTX(meshName)
		elif chunk == "NRMS":
			self.parse_NRMS(meshName)
		elif chunk == "PTYP":
			self.parse_PTYP()
		elif chunk == "PCNT":
			self.parse_PCNT()
		elif chunk == "PVTX":
			self.parse_PVTX(meshName)
		elif chunk == "GNDX":
			self.parse_GNDX()
		elif chunk == "MTGC":
			self.parse_MTGC()
		elif chunk == "MATS":
			self.parse_MATS(meshName)
		elif chunk == "UVAS":
			self.parse_UVAS(meshName)
		elif chunk == "UVBS":
			self.parse_UVBS(meshName)
            #next submesh
            print meshName
            meshNum += 1
	    
    def parse_LAYS(self, matNum):
	
	numLayers = self.inFile.read_long()
	for i in range(numLayers):
	    chunkSize, filterMode, shading, texID, \
	             tVertAnimID, coordID = self.inFile.read_long(6)
	    alpha = self.inFile.read_float()
	    #just skip extra tags
	    self.inFile.seek(chunkSize - 28, 1)
	    
    def parse_MTLS(self, size):
	
	sectEnd = self.inFile.tell() + size
        matNum = 0
	
	while self.inFile.tell() != sectEnd:
	    chunkSize, priorityPlane, renderMode = self.inFile.read_long(3)
	    chunk = self.inFile.read_string(4)
	    self.parse_LAYS(matNum)
	    matNum += 1

    def parse_VERS(self):
        
        version = self.inFile.read_long()
        
    def parse_file(self):
        '''Main parser method. Can be replaced'''
        
        filesize = self.inFile.filesize()
        magic = self.inFile.read_string(4)
        
        while self.inFile.tell() != filesize:
            chunk = self.inFile.read_string(4)
            chunkSize = self.inFile.read_long()
            print chunk, chunkSize
            if chunk == "MODL":
                modelName = self.parse_MODL()
            elif chunk == "GEOS":
                self.parse_GEOS(chunkSize, modelName)
	    elif chunk == "TEXS":
		self.parse_TEXS(chunkSize)
	    elif chunk == "MTLS":
		self.parse_MTLS(chunkSize)
            else:
                self.inFile.seek(chunkSize, 1)
        
def read_file(path):
    '''Read the file'''
    
    openFile = StructReader(open(path, 'rb'))
    obj = WarcraftIII_MDX(inFile=openFile)
    obj.parse_file()
    openFile.close()
    return obj

def write_file(path):
    
    pass

def definitions():
    '''Return the header, extension, and a description of the format'''
    
    return "MDLX", "MDX", "Warcraft 3 MDX"

if __name__ == '__main__':
    
    file1 = "ChaosKotoBeast.mdx"
    obj = read_file(file1)